package multithread.framework.threadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import multithread.framework.threadmethod.IThreadMethod;

import org.apache.log4j.Logger;

public class MethodExecutorService extends ThreadPoolExecutor implements
		ThreadExecuteTrigger {

	private ThreadExecuteListener threadExecuteListener = null;

	public void setThreadExecuteListener(
			ThreadExecuteListener threadExecuteListener) {
		this.threadExecuteListener = threadExecuteListener;
	}

	public MethodExecutorService(int corePoolSize, int maximumPoolSize,
			long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
	}

	public MethodExecutorService(int corePoolSize, int maximumPoolSize,
			long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
				threadFactory);
	}

	public MethodExecutorService(int corePoolSize, int maximumPoolSize,
			long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
				handler);
	}

	public MethodExecutorService(int corePoolSize, int maximumPoolSize,
			long keepAliveTime, TimeUnit unit,
			BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
			RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
				threadFactory, handler);
	}

	@Override
	protected void beforeExecute(Thread t, Runnable r) {
		super.beforeExecute(t, r);
		fireThreadBefore(t, r);
	}

	@Override
	protected void afterExecute(Runnable r, Throwable t) {
		super.afterExecute(r, t);
		fireThreadAfter(r, t);
	}

	/**
	 * recalled when thread pool shutdown
	 */
	@Override
	protected void terminated() {
		super.terminated();
		fireThreadAllAfter();
	}

	public void fireThreadBefore(Thread t, Runnable r) {
		if (threadExecuteListener == null)
			return;
		try {
			threadExecuteListener.threadBefore(t, r);
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).error("fireThreadBefore", e);
		}
	}

	public void fireThreadAllBefore() {
		if (threadExecuteListener == null)
			return;
		try {
			threadExecuteListener.threadAllBefore();
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).error("fireThreadAllBefore", e);
		}
	}

	public void fireThreadGroupBefore(IThreadMethod threadMethodGroup) {
		if (threadExecuteListener == null)
			return;
		try {
			threadExecuteListener.threadGroupBefore(threadMethodGroup);
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).error("fireThreadGroupBefore", e);
		}
	}

	public void fireThreadGroupAfter(IThreadMethod threadMethodGroup) {
		if (threadExecuteListener == null)
			return;
		try {
			threadExecuteListener.threadGroupAfter(threadMethodGroup);
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).error("fireThreadGroupAfter", e);
		}
	}

	public void fireThreadAfter(Runnable r, Throwable t) {
		if (threadExecuteListener == null)
			return;
		try {
			threadExecuteListener.threadAfter(r, t);
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).error("fireThreadAfter", e);
		}
	}

	public void fireThreadAllAfter() {
		if (threadExecuteListener == null)
			return;
		try {
			threadExecuteListener.threadAllAfter();
		} catch (Exception e) {
			Logger.getLogger(this.getClass()).error("fireThreadAllAfter", e);
		}
	}

}
